package com.elcom.emocbc.cbcgateway;

import com.elcom.ipc_udp_msg.CONVERT;
import com.elcom.ipc_udp_msg.MSG_DEFINE;
import com.elcom.ipc_udp_msg.control.MSG_GET_MODULE_INFO;
import com.elcom.ipc_udp_msg.control.MSG_GET_MODULE_INFO_RESP;
import com.elcom.util.ipc.IPCHandler;
import com.elcom.util.ipc.message.MESSAGE;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.concurrent.ThreadPoolExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ModuleMonitor implements Runnable {

    private final Logger logger = LoggerFactory.getLogger(ModuleMonitor.class);
    private final IPCHandler ipc;

    public ModuleMonitor(IPCHandler ipc) {
        this.ipc = ipc;
    }

    @Override
    public void run() {
        try {
            MESSAGE ipcMessage = ipc.getMessage();
            if (null != ipcMessage) {
                logger.debug("<<< Recv: " + ipcMessage);
                if (ipcMessage instanceof MSG_GET_MODULE_INFO) {
                    onModuleInfo((MSG_GET_MODULE_INFO) ipcMessage);
                } else {
                    logger.error("Ignore unsupported message -- " + ipcMessage);
                }
            }
        } catch (SocketTimeoutException e) {
            //Do nothing
        } catch (IOException ex) {
            logger.error("", ex);
        }

    }

    private void onModuleInfo(MSG_GET_MODULE_INFO req) {
        MSG_GET_MODULE_INFO_RESP resp = (MSG_GET_MODULE_INFO_RESP) ipc.createResponse(req);
        resp = (MSG_GET_MODULE_INFO_RESP) CONVERT.assign_req_to_resp(req, resp);
        String sentModule = CONVERT.getSourceModule(req);

        try {
            resp.RESPONSE_CODE = MSG_DEFINE.RESPONSE_CODE.E_OK;
            resp.MODULE_INFO = new String[]{getModuleInfo()};
        } catch (Throwable t) {
            logger.error("!!!Get module info!!!", t);
            resp.RESPONSE_CODE = MSG_DEFINE.RESPONSE_CODE.E_UNKNOWN;
        }
        //
        try {
            ipc.sentMessage(sentModule, resp);
            logger.debug("Sent -- " + resp);
        } catch (Throwable t) {
            logger.error("[!!!SEND!!!]", t);
        }
    }

    private String getModuleInfo() {
        ThreadPoolExecutor executor = CbcGateway.getInstance().getExecutor();
        int numOfThreadInPool = executor.getPoolSize();
        int activeThreads = executor.getActiveCount();
        long completedTaskCount = executor.getCompletedTaskCount();
        int queueSize = executor.getQueue().size();
        int remainingQueueSize = executor.getQueue().remainingCapacity();

        String rs = "Active Threads: " + activeThreads
                + " | Threads in pool: " + numOfThreadInPool
                + " | Queue Size: " + queueSize
                + " | Remaining queue size: " + remainingQueueSize
                + " | Completed task count: " + completedTaskCount;

        return rs;
    }
}
